package com.coursehub.exercise.service.impl;

import com.coursehub.exercise.entity.Exercise;
import com.coursehub.exercise.entity.Submission;
import com.coursehub.exercise.repository.ExerciseRepository;
import com.coursehub.exercise.repository.SubmissionRepository;
import com.coursehub.exercise.service.ExerciseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

@Service
@Transactional
public class ExerciseServiceImpl implements ExerciseService {
    
    @Autowired
    private ExerciseRepository exerciseRepository;
    
    @Autowired
    private SubmissionRepository submissionRepository;
    
    // 作业管理实现
    @Override
    public Exercise createExercise(Exercise exercise) {
        return exerciseRepository.save(exercise);
    }
    
    @Override
    public Exercise updateExercise(Long id, Exercise exercise) {
        Optional<Exercise> existingExercise = exerciseRepository.findById(id);
        if (existingExercise.isPresent()) {
            Exercise updated = existingExercise.get();
            updated.setTitle(exercise.getTitle());
            updated.setDescription(exercise.getDescription());
            updated.setType(exercise.getType());
            updated.setMaxScore(exercise.getMaxScore());
            updated.setDueDate(exercise.getDueDate());
            updated.setClassId(exercise.getClassId());
            return exerciseRepository.save(updated);
        }
        throw new RuntimeException("Exercise not found with id: " + id);
    }
    
    @Override
    public void deleteExercise(Long id) {
        exerciseRepository.deleteById(id);
    }
    
    @Override
    @Transactional(readOnly = true)
    public Optional<Exercise> getExerciseById(Long id) {
        return exerciseRepository.findById(id);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Exercise> getAllExercises() {
        return exerciseRepository.findAll();
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Exercise> getExercisesByCourse(Long courseId) {
        return exerciseRepository.findByCourseId(courseId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Exercise> getExercisesByClass(Long classId) {
        return exerciseRepository.findByClassId(classId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Exercise> getExercisesByTeacher(Long teacherId) {
        return exerciseRepository.findByTeacherId(teacherId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Exercise> getExercisesByType(Exercise.ExerciseType type) {
        return exerciseRepository.findByType(type);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Exercise> searchExercisesByTitle(String title) {
        return exerciseRepository.findByTitleContaining(title);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Exercise> getExercisesDueBetween(LocalDateTime startDate, LocalDateTime endDate) {
        return exerciseRepository.findExercisesDueBetween(startDate, endDate);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Exercise> getOverdueExercises() {
        return exerciseRepository.findOverdueExercises(LocalDateTime.now());
    }
    
    // 作业提交管理实现
    @Override
    public Submission submitExercise(Submission submission) {
        // 检查是否已经提交过
        if (submissionRepository.existsByExerciseIdAndStudentId(
                submission.getExerciseId(), submission.getStudentId())) {
            throw new RuntimeException("Student has already submitted this exercise");
        }
        return submissionRepository.save(submission);
    }
    
    @Override
    public Submission updateSubmission(Long id, Submission submission) {
        Optional<Submission> existingSubmission = submissionRepository.findById(id);
        if (existingSubmission.isPresent()) {
            Submission updated = existingSubmission.get();
            updated.setContent(submission.getContent());
            updated.setFilePath(submission.getFilePath());
            updated.setFileName(submission.getFileName());
            updated.setFileSize(submission.getFileSize());
            return submissionRepository.save(updated);
        }
        throw new RuntimeException("Submission not found with id: " + id);
    }
    
    @Override
    public void deleteSubmission(Long id) {
        submissionRepository.deleteById(id);
    }
    
    @Override
    @Transactional(readOnly = true)
    public Optional<Submission> getSubmissionById(Long id) {
        return submissionRepository.findById(id);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Submission> getSubmissionsByExercise(Long exerciseId) {
        return submissionRepository.findByExerciseId(exerciseId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Submission> getSubmissionsByStudent(Long studentId) {
        return submissionRepository.findByStudentId(studentId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public Optional<Submission> getSubmissionByExerciseAndStudent(Long exerciseId, Long studentId) {
        return submissionRepository.findByExerciseIdAndStudentId(exerciseId, studentId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Submission> getSubmissionsByStatus(Submission.SubmissionStatus status) {
        return submissionRepository.findByStatus(status);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Submission> getSubmissionsNeedingGrading() {
        return submissionRepository.findSubmissionsNeedingGrading();
    }
    
    // 评分管理实现
    @Override
    public Submission gradeSubmission(Long submissionId, Integer score, String feedback, Long gradedBy) {
        Optional<Submission> submissionOpt = submissionRepository.findById(submissionId);
        if (submissionOpt.isPresent()) {
            Submission submission = submissionOpt.get();
            submission.setScore(score);
            submission.setFeedback(feedback);
            submission.setGradedBy(gradedBy);
            submission.setGradedAt(LocalDateTime.now());
            submission.setStatus(Submission.SubmissionStatus.GRADED);
            return submissionRepository.save(submission);
        }
        throw new RuntimeException("Submission not found with id: " + submissionId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Submission> getGradedSubmissionsByExercise(Long exerciseId) {
        return submissionRepository.findGradedSubmissionsByExercise(exerciseId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public Double getAverageScoreByExercise(Long exerciseId) {
        return submissionRepository.calculateAverageScoreByExercise(exerciseId);
    }
    
    // 统计功能实现
    @Override
    @Transactional(readOnly = true)
    public long countExercisesByTeacher(Long teacherId) {
        return exerciseRepository.countByTeacherId(teacherId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public long countExercisesByCourse(Long courseId) {
        return exerciseRepository.countByCourseId(courseId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public long countExercisesByClass(Long classId) {
        return exerciseRepository.countByClassId(classId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public long countSubmissionsByExercise(Long exerciseId) {
        return submissionRepository.countByExerciseId(exerciseId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public long countSubmissionsByStudent(Long studentId) {
        return submissionRepository.countByStudentId(studentId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public long countGradedSubmissionsByExercise(Long exerciseId) {
        return submissionRepository.countByExerciseIdAndStatus(exerciseId, Submission.SubmissionStatus.GRADED);
    }
    
    @Override
    @Transactional(readOnly = true)
    public boolean hasStudentSubmitted(Long exerciseId, Long studentId) {
        return submissionRepository.existsByExerciseIdAndStudentId(exerciseId, studentId);
    }
}